package com.jeasonzhao.commons.utils;

public class ChineseNumber
{
    private static final String SimpleNumberSymbol = "〇,一,二,三,四,五,六,七,八,九";
    private static final String TraditionalNumberSymbol = "零,壹,贰,叁,肆,伍,陆,柒,捌,玖";
    private static final String AllNumberSymbol = SimpleNumberSymbol + "," + TraditionalNumberSymbol;
    public static final String AllNumberSymbolWithoutComma = "〇一二三四五六七八九零壹贰叁肆伍陆柒捌玖";
    private static final String SimpleUnitSymbol = "十百千万亿";
    private static final String TraditionaUnitSymbol = "拾佰仟万亿";
    private static final String NumberRegex =
        "^\\s*[个拾佰仟点元圆角分正负廿卅两十百千万亿"
        + AllNumberSymbolWithoutComma
        + "\\s\\.,]+\\s*$";
    private static final String UnitRegex = "^.*[个十百千万亿拾佰仟万亿]+.*$";
    private static final int SHI = 0,BAI = 1,QIAN = 2,WAN = 3,YI = 4;
    private static char[] SimpleNumberSymbolArray = null;
    private static char[] TraditionalNumberSymbolArray = null;
    private static char[] AllNumberSymbolArray = null;
    static
    {
        SimpleNumberSymbolArray = SimpleNumberSymbol.replaceAll(",","").toCharArray();
        TraditionalNumberSymbolArray = TraditionalNumberSymbol.replaceAll(",","").toCharArray();
        AllNumberSymbolArray = AllNumberSymbol.replaceAll(",","").toCharArray();
    }

    public static boolean isChinesNumber(String s)
    {
        return Algorithms.isEmpty(s) ? false : RegexHelper.matches(NumberRegex,s);
    }

    public static int toInt(String strInput)
    {
        return ConvertEx.toInt(toDouble(strInput));
    }

    private static double fromPlainText(String strInput)
    {
        String news = "";
        final String xall = AllNumberSymbol.replaceAll(",","");
        for(char c : toAsciiNumber(strInput).toCharArray())
        {
            if(Character.isDigit(c)
               || c == '.' || c == '+' || c == '-')
            {
                news += c;
            }
            else if(xall.indexOf(c) >= 0)
            {
                news += "" + (xall.indexOf(c) % 10);
            }
            else
            {
                continue;
            }
        }
        //System.out.println(strInput+"= "+news);
        return ConvertEx.toDouble(news);
    }

    public static double toDouble(String strInput)
    {
        if(null == strInput || strInput.trim().length() < 1)
        {
            return 0f;
        }
        strInput = strInput.replaceAll("〇","零");
        if(RegexHelper.matches(UnitRegex,strInput) == false)
        {
            //Plain number
            return fromPlainText(strInput);
        }
        String str = expandChineseNumString(strInput);
        str = toAsciiNumber(str);
        try
        {
            return ConvertEx.toDouble(str);
        }
        catch(Exception ex)
        {
            throw new java.lang.IllegalArgumentException("转换数字错误，不能转换 " + strInput + ": " + ex.getMessage());
        }
    }

    public static String toAsciiNumber(double lp)
    {
        String s = Algorithms.DEFAULT_DOUBLE_FORMAT.format(lp);
        s = expandChineseNumString(s);
        return toAsciiNumber(s);
    }

    private static String toAsciiNumber(String str)
    {
        str = str.replaceAll("廿","二十")
            .replaceAll("负","-")
            .replaceAll("的","")
            .replaceAll("正","")
            .replaceAll("卅","三十")
            .replaceAll("仨","三")
            .replaceAll("俩","二")
            .replaceAll("两","二")
            .replaceAll("点",".")
            .replaceAll("元",".")
            .replaceAll("圆",".")
            .replaceAll("园",".")
            .replaceAll("个","")
            .replaceAll("十","")
            .replaceAll("百","")
            .replaceAll("千","")
            .replaceAll(",","")
            .replaceAll("万","")
            .replaceAll("亿","")
            .replaceAll("角","")
            .replaceAll("分","")
            .replaceAll("拾","")
            .replaceAll("佰","")
            .replaceAll("仟","")
            ;
        for(int n = AllNumberSymbolArray.length - 1;n >= 0;n--)
        {
            int nn = n % 10;
            char nc = (char) ((int) '0' + nn);
            str = str.replaceAll("" + AllNumberSymbolArray[n],"" + nc);
        }
        return str;
    }

    private static String expandChineseNumString(String strInput)
    {
        String str = strInput.trim()
            .replaceAll("廿","二十")
            .replaceAll("的","")
            .replaceAll("卅","三十")
            .replaceAll("仨","三")
            .replaceAll("俩","二")
            .replaceAll("两","二")
            .replaceAll("点",".")
            .replaceAll("元",".")
            .replaceAll("圆",".")
            .replaceAll("园",".");
        str = RegexHelper.replaceAll(str,"\\s+","");
        //Expand
        int nindex = str.lastIndexOf('.');
        String mani = str;
        String part = "";
        if(nindex >= 0)
        {
            mani = str.substring(0,nindex);
            part = str.substring(nindex + 1);
        }
        char[] a1 = TraditionaUnitSymbol.toCharArray();
        char[] a2 = SimpleUnitSymbol.toCharArray();
        String newmain = "";
        int nlast = -1;
        for(char c : mani.toCharArray())
        {
            nindex = -1;
            for(int n = 0;n < a1.length && n < a2.length;n++)
            {
                if(a1[n] == c || a2[n] == c)
                {
                    nindex = n;
                    break;
                }
            }
            if(nindex <= 0)
            {
                nlast = nindex == 0 ? nindex : nlast;
                newmain += c;
            }
            else
            {
                if(nindex >= nlast || (nindex + 1) == nlast)
                {
                    newmain += c;
                }
                else
                {
                    String ns = newmain.length() > 0 ? newmain.substring(newmain.length() - 1) : "";
                    if(IsUnitChar(ns.toCharArray()[0]))
                    {
                        ns = "";
                    }
                    else
                    {
                        newmain = newmain.length() > 0 ? newmain.substring(0,newmain.length() - 1) : "";
                    }
                    for(int n = nlast - 1;n > nindex;n--)
                    {
                        newmain += "零" + a1[n];
                    }
                    newmain += ns + "" + c;
                }
                nlast = nindex;
            }
        }
        if(nlast > 0)
        {
            String ns = newmain.length() > 0 ? newmain.substring(newmain.length() - 1) : "";
            char clast = ns.toCharArray()[0];
            if(clast == a1[YI] || clast == a2[YI])
            {
                newmain += "零仟零佰零十零万";
                nlast = WAN;
            }
            if(IsUnitChar(clast))
            {
                ns = "";
            }
            else
            {
                newmain = newmain.length() > 0 ? newmain.substring(0,newmain.length() - 1) : "";
            }
            for(int n = nlast - 1;n >= 0;n--)
            {
                newmain += "零" + a1[n];
            }
            newmain += ns;
        }
        while(newmain.contains("零零"))
        {
            newmain = newmain.replaceAll("零零","零");
        }
        if(newmain.length() < 1 || IsUnitChar(newmain.toCharArray()[newmain.length() - 1]))
        {
            newmain += "零";
        }
        newmain = newmain
            .replaceAll("拾万","拾零万")
            .replaceAll("十万","十零万")
            .replaceAll("佰万","佰零拾零万")
            .replaceAll("百万","佰零拾零万")
            .replaceAll("仟万","仟零佰零拾零万")
            .replaceAll("千万","仟零佰零拾零万")

            .replaceAll("拾亿","拾零亿")
            .replaceAll("十亿","十零亿")
            .replaceAll("佰亿","佰零拾零亿")
            .replaceAll("百亿","佰零拾零亿")
            .replaceAll("仟亿","仟零佰零拾零亿")
            .replaceAll("千亿","仟零佰零拾零亿")

            .replaceAll("亿零万","亿")
            ;
        if(newmain.startsWith("十") || newmain.startsWith("拾"))
        {
            newmain = "一" + newmain;
        }
        str = part.length() > 0 ? (newmain + "点" + part) : newmain;
        return str;
    }

    private static boolean IsUnitChar(char c)
    {
        return TraditionaUnitSymbol.indexOf(c) >= 0 || SimpleUnitSymbol.indexOf(c) >= 0;
    }

    private static String subPart2String(String str,char[] ennumber,char[] numbers,char[] units)
    {
        String newleft = "";
        //To chinese characters
        for(char c : str.toCharArray())
        {
            for(int n = 0;n < ennumber.length;n++)
            {
                if(c == ennumber[n])
                {
                    newleft += numbers[n];
                }
            }
        }
        if(null == units)
        {
            return newleft;
        }
        String cleft = "";
        char[] ary = newleft.toCharArray();
        char END = (char) 0;
        //System.Console.WriteLine(">>>>>" + newleft);
        for(int n = 0;n < ary.length;n++)
        {
            char p = END;
            switch(ary.length - n)
            {
                case 2: //21
                case 6: //1234,56
                    p = units[SHI];
                    break;
                case 3: //121
                case 7: //1234,123
                    p = units[BAI];
                    break;
                case 4: //1234
                case 8: //1234,1234
                    p = units[QIAN];
                    break;
                case 5: //12345
                case 9:
                    p = units[WAN];
                    break;
            }
            if(p != END)
            {
                cleft += "" + ary[n] + "" + p;
            }
            else
            {
                cleft += "" + ary[n];
            }
        }
        return cleft;
    }

    public static String toCurrencyString(double lfInit)
    {
        return toString(lfInit,false,true,false);
    }

    public static String toFullString(double lfInit)
    {
        return toString(lfInit,false,false,true);
    }

    public static String toString(double lfInit)
    {
        return toString(lfInit,false,false,false);
    }

    public static String toString(double lfInit
                                  ,boolean isSimple
                                  ,boolean showmoney,boolean showall)
    {
        char[] ennumber = "0123456789".toCharArray();
        char[] numbers = isSimple ? SimpleNumberSymbolArray : TraditionalNumberSymbolArray;
        char[] units = (isSimple ? SimpleUnitSymbol : TraditionaUnitSymbol).toCharArray();
        boolean lessthanzero = lfInit < 0;
        if(lessthanzero)
        {
            lfInit = 0 - lfInit;
        }
        String initString = showmoney ?
            Algorithms.DEFAULT_CURRENCY_FORMAT.format(lfInit)
            : Algorithms.DEFAULT_DOUBLE_FORMAT.format(lfInit);
        int nindex = initString.indexOf('.');
        String right = "";
        String left = initString;
        if(nindex >= 0)
        {
            right = initString.substring(nindex + 1);
            left = initString.substring(0,nindex);
        }
        String strRet = "";
        while(left.length() > 0)
        {
            String t = left.length() > 8 ? left.substring(left.length() - 8) : left;
            left = left.length() > 8 ? left.substring(0,left.length() - 8) : "";
            if(strRet.length() > 0)
            {
                strRet = "" + units[YI] + strRet;
            }
            strRet = subPart2String(t,ennumber,numbers,units) + strRet;
        }
        if(showall == false)
        {
            while(strRet.contains("零" + units[SHI])
                  || strRet.contains("零" + units[BAI])
                  || strRet.contains("零" + units[QIAN])
                  || strRet.contains("零" + units[WAN])
                  || strRet.contains("零" + units[YI])
                  || strRet.contains("" + units[YI] + "" + units[WAN])
                  || strRet.contains("零零"))
            {

                strRet = strRet.replaceAll("零" + units[SHI],"零");
                strRet = strRet.replaceAll("零" + units[BAI],"零");
                strRet = strRet.replaceAll("零" + units[QIAN],"零");
                strRet = strRet.replaceAll("零" + units[WAN],"" + units[WAN]);
                strRet = strRet.replaceAll("零" + units[YI],"" + units[YI]);
                strRet = strRet.replaceAll("" + units[YI] + "" + units[WAN],"" + units[YI]);
                strRet = strRet.replaceAll("零零","零");
            }
            while(strRet.endsWith("零"))
            {
                strRet = strRet.substring(0,strRet.length() - 1);
            }
        }

        right = subPart2String(right,ennumber,numbers,null);
        while(right != null && right.length() > 0 && right.endsWith("零"))
        {
            right = right.substring(0,right.length() - 1);
        }
        if(showmoney)
        {
            strRet += isSimple ? "元" : "圆";
        }
        if(right != null && right.length() > 0)
        {
            if(showmoney)
            {
                right = right.length() > 1 ? (right.toCharArray()[0] + "角" + right.toCharArray()[1] + "分") :
                    (showall ? (right.toCharArray()[0] + "角零分") : (right.toCharArray()[0] + "角"));
            }
            else
            {
                strRet += "点" + right;
            }
        }
        if(strRet.length() < 1)
        {
            strRet = "零";
        }
        else if(lessthanzero)
        {
            strRet = "负" + strRet;
        }
        return strRet;
    }
}
